// 进阶内容是在前文1，2，3，4的基础上，更进一步

// 类型别名
// 简单的说就是给类型取一个名字，方便后续使用，一般来说，类型别名多用于联合类型
// 语法为： type 类型名 = 联合类型或单一类型
type Str = string; // 定义一个字符串类型
type Func = () => string; // 定义一个返回值为字符串类型的函数类型
type StrOrFunc = Str | Func; // 联合类型
function func(str: StrOrFunc): string {
  if (typeof str === 'string') {
    return str;
  }
  return str();
}


// 字符串字面量类型
// 首先这是一种类型，用来约束变量具体的取值范围
type Color = 'Red' | 'Blue' | 'Green';
let color:Color = 'Red'; // 编译正常
// let color:Color = 'red'; // 编译错误


// 元组
// 数组一般是相同类型的集合，当然我们也可以使用泛型，这样可以让数组中存放各种类型的数据。数组对于存放数据的顺序没有要求，只要满足类型即可
let arr: Array<number | string> = ['2', 1]; // 定义一个泛型数组，index=0的数据是字符串还是数字对于数组来说是不关心的
// 元组是不同类型的集合，当然也可以是同一类型。其对存放的数据有顺序要求，并且在初始化时会限制越界
let num: [number, number] = [1, 2]
// let num: [number, number] = [1, 2, 3]; // 编译错误
let str: [string, number] = ['1', 2];
// let str: [string, number] = [1, '2']; // 编译错误
// 如果我们想继续在元组中添加元素，即使会越界，那么也只能添加兼容元组类型的数据才可以
str.push('3'); // 正常
// str.push(false); // 编译错误


// 枚举
// 如果要限制取值范围，可以考虑使用枚举，例如星期、颜色、方向等。定义时使用enum
enum Direct {
  Left,
  Right,
  Up,
  Down
}
console.log(Direct.Left, Direct[0]); // 0 Left


